//
// Created by 原帅 on 2022/10/15.
//

#include <cassert>
#include "RAcceptor.h"
#include "sys/socket.h"
#include "arpa/inet.h"
#include "RLog.h"
#include "strings.h"

RAcceptor::RAcceptor(int port, int type,char *ipAddr) : port(port), type(type) {
    this->serveraddr.sin_port = htons(port);
    if (ipAddr!= nullptr)
    {
        for (int i = 0; i < IP_STR_MAX_SIZE; ++i) {
            if (ipAddr[i] != 0)
            {
                this->ipv4str[i] = ipAddr[i];
            }
        }
        this->serveraddr.sin_addr.s_addr =inet_addr(this->ipv4str);
    } else
    {
        snprintf(ipv4str,IP_STR_MAX_SIZE,"0.0.0.0");
        this->serveraddr.sin_addr.s_addr =INADDR_ANY;
    }

    this->ipv4 = serveraddr.sin_addr.s_addr;
    this->serveraddr.sin_family = AF_INET;
}

RLinkInfo RAcceptor::doAccept() {
    bzero(&this->clientaddr,sizeof(struct sockaddr));
    socklen_t socklen = 0;
    int fd = accept(this->sockfd,(struct sockaddr*) &this->clientaddr,&socklen);
    RLinkInfo rLinkInfo(fd, this->clientaddr);
    return rLinkInfo;
}

int RAcceptor::doListen() {
    int iRet = 0;
    switch (type) {
        case SOCK_STREAM:
            iRet = socket(AF_INET,type,IPPROTO_TCP);
            break;
        case SOCK_DGRAM:
            iRet = socket(AF_INET,type,IPPROTO_UDP);
        default:
            RLogErr("Unknow socket type:%d",type);
            assert(0);
    }
    if (iRet>0)
    {
        this->sockfd = iRet;
    } else {
        RLogErr("socket error:%d", iRet);
        return iRet;
    }
    iRet = bind(this->sockfd,(struct sockaddr*)&this->serveraddr,sizeof(struct sockaddr));
    if (iRet == -1) {
        RLogErr("bind error:%d",iRet);
        return iRet;
    }
    iRet = listen(this->sockfd,64);
    if (iRet == -1) {
        RLogErr("listen error:%d",iRet);
        return iRet;
    }
    return 0;
}

int RAcceptor::getSockfd() const {
    return sockfd;
}

const char *RAcceptor::getIpv4Str() const {
    return ipv4str;
}

int RAcceptor::getPort() const {
    return port;
}
